// __COPYRIGHT_START__
// Package Name : 
// File Name : random.cc
// Copyright 2003 Scott M. Duke-Sylvester and the ATLSS
// project.
//
//
// All rights reserved. No part of this source code maybe reproduced, stored
// in a retrieval system or transmitted in any form  or by any means, electrontic
// mechanical photocopying recording or otherwise without prior written
// permission of the above mentioned copyright holders.
// __COPYRIGHT_END__
#include <sys/time.h>

#include "myrandom.h"

unsigned int rng_endian_swap(char* acp_val, size_t at_size )
{
	char lc_tmp;

	switch ( at_size ) {
		case 1:
			return 0;
		case 2: {
			lc_tmp = acp_val[0]; 
			acp_val[0] = acp_val[1]; 
			acp_val[1] = lc_tmp;
			return 0;
		}
		case 4: {
			lc_tmp = acp_val[0]; 
			acp_val[0] = acp_val[3]; 
			acp_val[3] = lc_tmp;

			lc_tmp = acp_val[1]; 
			acp_val[1] = acp_val[2]; 
			acp_val[2] = lc_tmp;
			return 0;
		}
		case 8: {
			lc_tmp = acp_val[0];
			acp_val[0] = acp_val[7];
			acp_val[7] = lc_tmp;

			lc_tmp = acp_val[1];
			acp_val[1] = acp_val[6];
			acp_val[6] = lc_tmp;

			lc_tmp = acp_val[2];
			acp_val[2] = acp_val[5];
			acp_val[5] = lc_tmp;
			
			lc_tmp = acp_val[3];
			acp_val[3] = acp_val[4];
			acp_val[4] = lc_tmp;
			return 0;
		}
		case 12: {
			lc_tmp = acp_val[0];
			acp_val[0] = acp_val[11];
			acp_val[11] = lc_tmp;

			lc_tmp = acp_val[1];
			acp_val[1] = acp_val[10];
			acp_val[10] = lc_tmp;

			lc_tmp = acp_val[2];
			acp_val[2] = acp_val[9];
			acp_val[9] = lc_tmp;
			
			lc_tmp = acp_val[3];
			acp_val[3] = acp_val[8];
			acp_val[8] = lc_tmp;

			lc_tmp = acp_val[4];
			acp_val[4] = acp_val[7];
			acp_val[7] = lc_tmp;

			lc_tmp = acp_val[5];
			acp_val[5] = acp_val[6];
			acp_val[6] = lc_tmp;
			return 0;
		}
		default:
			return 1;
	}
}

gsl_rng* Random::mtp_random = NULL;

Random::Random()
{
	if ( mtp_random == NULL ) {
		mtp_random = gsl_rng_alloc(gsl_rng_mt19937);
		timeval lC_time;
		gettimeofday(&lC_time, 0);
		long ll_seed = long(lC_time.tv_usec&0xfff7f);
		// rng_endian_swap( (char*)&ll_seed, sizeof(ll_seed) );
		std::cout << "ll_seed = " << ll_seed << std::endl;
		gsl_rng_set(mtp_random, ll_seed);

		// Warm up the random number generator.	
		for ( int i = 0; i < 10000; i++) gsl_rng_uniform();
	}
}

Random::Random( const Random& ) {}

Random::~Random() {}

double            Random::gsl_rng_uniform    ()                    const { return ::gsl_rng_uniform(mtp_random); }
unsigned long int Random::gsl_rng_uniform_int(unsigned long int n) const { return ::gsl_rng_uniform_int(mtp_random, n); }

double            Random::gsl_ran_flat       (double a, double b)  const { return ::gsl_ran_flat(mtp_random,a,b); }
unsigned int      Random::gsl_ran_poisson    (double mu)           const { return ::gsl_ran_poisson(mtp_random, mu); } 

unsigned long int Random::gsl_rng_max        ()                    const { return ::gsl_rng_max(mtp_random);}
unsigned long int Random::gsl_rng_min        ()                    const { return ::gsl_rng_min(mtp_random);}

void Random::gsl_ran_shuffle(void* base, size_t n, size_t size) const { ::gsl_ran_shuffle(mtp_random,base,n,size); return;}
